/**
 * @file 时间选择器Hook
 * @description 提供时间选择相关的通用逻辑，包括时间格式控制、下拉菜单控制、时间百分比转换等
 * @date 2024-08-26
 * 
 * 本组合式函数实现了以下功能：
 * 1. 支持24小时格式的时间选择（HH:MM）
 * 2. 提供开始时间和结束时间的管理
 * 3. 支持时间输入验证和冲突处理
 * 4. 下拉式时间选择器控制
 * 5. 时间与百分比位置之间的相互转换
 * 6. 完整的TypeScript类型支持
 * 
 * 该组件从TrackPlayer组件中提取并抽象了时间选择逻辑，使其可以被其他需要时间选择功能的组件复用。
 */

// Vue相关导入
// @ts-ignore - uni-app环境下Vue导入需要忽略类型检查
import { ref, reactive, onUnmounted } from 'vue';
// @ts-ignore - uni-app环境下Vue类型导入需要忽略类型检查
import type { Ref } from 'vue';

/**
 * 时间选择器选项
 */
export interface TimeSelectorOptions {
  /** 是否启用范围选择 */
  enableRange?: boolean;
  /** 初始开始时间 (HH:MM格式) */
  initialStartTime?: string;
  /** 初始结束时间 (HH:MM格式) */
  initialEndTime?: string;
  /** 最小时间间隔 (分钟) */
  minTimeDifference?: number;
  /** 时间变更回调 */
  onTimeChange?: (type: 'start' | 'end', time: string, percentage: number) => void;
  /** 时间冲突回调 */
  onTimeConflict?: (type: 'start' | 'end', invalidTime: string, currentTime: string) => void;
}

/**
 * 时间范围状态
 */
export interface TimeRangeState {
  /** 是否正在编辑开始时间 */
  isEditingStartTime: Ref<boolean>;
  /** 是否正在编辑结束时间 */
  isEditingEndTime: Ref<boolean>;
  /** 原始开始时间 */
  originalStartTime: Ref<string>;
  /** 原始结束时间 */
  originalEndTime: Ref<string>;
  /** 格式化的开始时间 */
  formattedStartTime: Ref<string>;
  /** 格式化的结束时间 */
  formattedEndTime: Ref<string>;
  /** 开始时间百分比 */
  startTimePercentage: Ref<number>;
  /** 结束时间百分比 */
  endTimePercentage: Ref<number>;
}

/**
 * 时间选择器助手对象
 */
export interface TimeSelectorHelper {
  /** 处理输入框获取焦点事件 */
  handleFocus: () => void;
  /** 处理输入框失去焦点事件 */
  handleBlur: () => void;
  /** 处理输入事件 */
  handleInput: () => void;
  /** 处理点击事件 */
  handleClick: (event?: Event) => void;
}

/**
 * 时间格式正则表达式
 */
const TIME_PATTERN = /^([0-1]?[0-9]|2[0-3]):([0-5][0-9])$/;

/**
 * 从时间字符串中获取小时
 * @param time 时间字符串 (HH:MM)
 * @returns 小时数
 */
export function getHourFromTime(time: string): number {
  if (!TIME_PATTERN.test(time)) return 0;
  const hours = parseInt(time.split(':')[0], 10);
  return isNaN(hours) ? 0 : hours;
}

/**
 * 从时间字符串中获取分钟
 * @param time 时间字符串 (HH:MM)
 * @returns 分钟数
 */
export function getMinuteFromTime(time: string): number {
  if (!TIME_PATTERN.test(time)) return 0;
  const minutes = parseInt(time.split(':')[1], 10);
  return isNaN(minutes) ? 0 : minutes;
}

/**
 * 时间选择器Hook
 * @param options 配置选项
 * @returns 时间选择相关状态和方法
 */
export function useTimeSelector(options: TimeSelectorOptions = {}) {
  // 配置默认值
  const {
    enableRange = true,
    initialStartTime = '00:00',
    initialEndTime = '23:59',
    minTimeDifference = 1,
    onTimeChange,
    onTimeConflict
  } = options;
  
  // 时间范围状态
  const timeRangeState: TimeRangeState = {
    isEditingStartTime: ref(false),
    isEditingEndTime: ref(false),
    originalStartTime: ref(''),
    originalEndTime: ref(''),
    formattedStartTime: ref(initialStartTime),
    formattedEndTime: ref(initialEndTime),
    startTimePercentage: ref(timeToPercentage(initialStartTime)),
    endTimePercentage: ref(timeToPercentage(initialEndTime))
  };
  
  // 下拉框状态
  const showStartTimeDropdown = ref(false);
  const showEndTimeDropdown = ref(false);
  
  // 小时和分钟数组
  const hours = Array.from({ length: 24 }, (_, i) => i);
  const minutes = Array.from({ length: 60 }, (_, i) => i);
  
  /**
   * 将时间转换为百分比
   * @param time 时间字符串 (HH:MM)
   * @returns 百分比 (0-100)
   */
  function timeToPercentage(time: string): number {
    const hour = getHourFromTime(time);
    const minute = getMinuteFromTime(time);
    
    // 总分钟数除以一天的总分钟数 (24 * 60)
    const totalMinutes = hour * 60 + minute;
    return (totalMinutes / (24 * 60)) * 100;
  }
  
  /**
   * 将百分比转换为时间
   * @param percentage 百分比 (0-100)
   * @returns 时间字符串 (HH:MM)
   */
  function percentageToTime(percentage: number): string {
    // 假设一天24小时
    const totalMinutes = 24 * 60;
    const minutes = Math.floor((percentage / 100) * totalMinutes);
    const hours = Math.floor(minutes / 60);
    const mins = minutes % 60;
    return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`;
  }
  
  /**
   * 更新开始时间百分比
   * @param time 可选的时间字符串，不传则使用当前值
   * @returns 计算后的百分比
   */
  function updateStartTimePercentage(time?: string): number {
    const timeStr = time || timeRangeState.formattedStartTime.value;
    if (!TIME_PATTERN.test(timeStr)) return timeRangeState.startTimePercentage.value;
    
    const percentage = timeToPercentage(timeStr);
    timeRangeState.startTimePercentage.value = percentage;
    
    // 触发变更回调
    if (onTimeChange) {
      onTimeChange('start', timeStr, percentage);
    }
    
    return percentage;
  }
  
  /**
   * 更新结束时间百分比
   * @param time 可选的时间字符串，不传则使用当前值
   * @returns 计算后的百分比
   */
  function updateEndTimePercentage(time?: string): number {
    const timeStr = time || timeRangeState.formattedEndTime.value;
    if (!TIME_PATTERN.test(timeStr)) return timeRangeState.endTimePercentage.value;
    
    const percentage = timeToPercentage(timeStr);
    timeRangeState.endTimePercentage.value = percentage;
    
    // 触发变更回调
    if (onTimeChange) {
      onTimeChange('end', timeStr, percentage);
    }
    
    return percentage;
  }
  
  /**
   * 切换开始时间下拉框
   * @param event 事件对象
   */
  function toggleStartTimeDropdown(event?: Event): void {
    if (event) event.stopPropagation();
    
    // 关闭另一个下拉框
    if (showEndTimeDropdown.value) {
      closeEndTimeDropdown();
    }
    
    // 切换当前下拉框
    showStartTimeDropdown.value = !showStartTimeDropdown.value;
    
    // 添加文档点击事件监听，以便在点击外部时关闭下拉框
    if (showStartTimeDropdown.value) {
      setTimeout(() => {
        document.addEventListener('click', closeStartTimeDropdown);
      }, 0);
    } else {
      document.removeEventListener('click', closeStartTimeDropdown);
    }
  }
  
  /**
   * 切换结束时间下拉框
   * @param event 事件对象
   */
  function toggleEndTimeDropdown(event?: Event): void {
    if (event) event.stopPropagation();
    
    // 关闭另一个下拉框
    if (showStartTimeDropdown.value) {
      closeStartTimeDropdown();
    }
    
    // 切换当前下拉框
    showEndTimeDropdown.value = !showEndTimeDropdown.value;
    
    // 添加文档点击事件监听，以便在点击外部时关闭下拉框
    if (showEndTimeDropdown.value) {
      setTimeout(() => {
        document.addEventListener('click', closeEndTimeDropdown);
      }, 0);
    } else {
      document.removeEventListener('click', closeEndTimeDropdown);
    }
  }
  
  /**
   * 关闭开始时间下拉框
   */
  function closeStartTimeDropdown(): void {
    showStartTimeDropdown.value = false;
    document.removeEventListener('click', closeStartTimeDropdown);
  }
  
  /**
   * 关闭结束时间下拉框
   */
  function closeEndTimeDropdown(): void {
    showEndTimeDropdown.value = false;
    document.removeEventListener('click', closeEndTimeDropdown);
  }
  
  /**
   * 关闭所有时间下拉框
   */
  function closeAllDropdowns(): void {
    closeStartTimeDropdown();
    closeEndTimeDropdown();
  }
  
  /**
   * 选择开始时间的小时
   * @param hour 小时值 (0-23)
   */
  function selectStartHour(hour: number): void {
    const minute = getMinuteFromTime(timeRangeState.formattedStartTime.value);
    const newTime = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
    
    // 验证新时间是否有效
    if (validateUpdatedTime('start', newTime)) {
      timeRangeState.formattedStartTime.value = newTime;
      updateStartTimePercentage();
    }
    
    // 不关闭下拉框，允许用户继续选择分钟
  }
  
  /**
   * 选择开始时间的分钟
   * @param minute 分钟值 (0-59)
   */
  function selectStartMinute(minute: number): void {
    const hour = getHourFromTime(timeRangeState.formattedStartTime.value);
    const newTime = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
    
    // 验证新时间是否有效
    if (validateUpdatedTime('start', newTime)) {
      timeRangeState.formattedStartTime.value = newTime;
      updateStartTimePercentage();
    }
    
    // 关闭下拉框，因为小时和分钟都已选择
    closeStartTimeDropdown();
  }
  
  /**
   * 选择结束时间的小时
   * @param hour 小时值 (0-23)
   */
  function selectEndHour(hour: number): void {
    const minute = getMinuteFromTime(timeRangeState.formattedEndTime.value);
    const newTime = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
    
    // 验证新时间是否有效
    if (validateUpdatedTime('end', newTime)) {
      timeRangeState.formattedEndTime.value = newTime;
      updateEndTimePercentage();
    }
    
    // 不关闭下拉框，允许用户继续选择分钟
  }
  
  /**
   * 选择结束时间的分钟
   * @param minute 分钟值 (0-59)
   */
  function selectEndMinute(minute: number): void {
    const hour = getHourFromTime(timeRangeState.formattedEndTime.value);
    const newTime = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
    
    // 验证新时间是否有效
    if (validateUpdatedTime('end', newTime)) {
      timeRangeState.formattedEndTime.value = newTime;
      updateEndTimePercentage();
    }
    
    // 关闭下拉框，因为小时和分钟都已选择
    closeEndTimeDropdown();
  }
  
  /**
   * 验证更新后的时间是否满足约束条件
   * @param type 时间类型 (start | end)
   * @param newTime 新的时间字符串
   * @returns 是否有效
   */
  function validateUpdatedTime(type: 'start' | 'end', newTime: string): boolean {
    // 首先验证时间格式
    if (!TIME_PATTERN.test(newTime)) return false;
    
    // 如果不需要范围验证，则直接返回有效
    if (!enableRange) return true;
    
    const startHour = type === 'start' ? getHourFromTime(newTime) : getHourFromTime(timeRangeState.formattedStartTime.value);
    const startMinute = type === 'start' ? getMinuteFromTime(newTime) : getMinuteFromTime(timeRangeState.formattedStartTime.value);
    const endHour = type === 'end' ? getHourFromTime(newTime) : getHourFromTime(timeRangeState.formattedEndTime.value);
    const endMinute = type === 'end' ? getMinuteFromTime(newTime) : getMinuteFromTime(timeRangeState.formattedEndTime.value);
    
    const startTotalMinutes = startHour * 60 + startMinute;
    const endTotalMinutes = endHour * 60 + endMinute;
    
    // 验证开始时间不晚于结束时间，并且两者间隔不小于最小间隔
    if (type === 'start' && startTotalMinutes >= endTotalMinutes - minTimeDifference) {
      if (onTimeConflict) {
        onTimeConflict('start', newTime, timeRangeState.formattedStartTime.value);
      }
      return false;
    }
    
    // 验证结束时间不早于开始时间，并且两者间隔不小于最小间隔
    if (type === 'end' && endTotalMinutes <= startTotalMinutes + minTimeDifference) {
      if (onTimeConflict) {
        onTimeConflict('end', newTime, timeRangeState.formattedEndTime.value);
      }
      return false;
    }
    
    return true;
  }
  
  /**
   * 验证时间输入
   * @param type 时间类型 (start | end)
   * @returns 是否有效
   */
  function validateTime(type: 'start' | 'end'): boolean {
    if (type === 'start') {
      // 验证时间格式
      if (!TIME_PATTERN.test(timeRangeState.formattedStartTime.value)) {
        timeRangeState.formattedStartTime.value = timeRangeState.originalStartTime.value;
        return false;
      }
      
      // 如果启用范围选择，验证开始时间不晚于结束时间
      if (enableRange) {
        return validateUpdatedTime('start', timeRangeState.formattedStartTime.value);
      }
    } else {
      // 验证时间格式
      if (!TIME_PATTERN.test(timeRangeState.formattedEndTime.value)) {
        timeRangeState.formattedEndTime.value = timeRangeState.originalEndTime.value;
        return false;
      }
      
      // 如果启用范围选择，验证结束时间不早于开始时间
      if (enableRange) {
        return validateUpdatedTime('end', timeRangeState.formattedEndTime.value);
      }
    }
    
    return true;
  }
  
  /**
   * 创建时间选择器助手对象
   * @param type 时间类型 (start | end)
   * @returns 时间选择器助手对象
   */
  function createTimeSelectorHelper(type: 'start' | 'end'): TimeSelectorHelper {
    const state = type === 'start' 
      ? { 
          editing: timeRangeState.isEditingStartTime,
          original: timeRangeState.originalStartTime,
          formatted: timeRangeState.formattedStartTime,
          updatePercentage: updateStartTimePercentage,
          toggleDropdown: toggleStartTimeDropdown
        } 
      : {
          editing: timeRangeState.isEditingEndTime,
          original: timeRangeState.originalEndTime,
          formatted: timeRangeState.formattedEndTime,
          updatePercentage: updateEndTimePercentage,
          toggleDropdown: toggleEndTimeDropdown
        };

    return {
      handleFocus: () => {
        state.editing.value = true;
        state.original.value = state.formatted.value;
        closeAllDropdowns();
      },
      
      handleBlur: () => {
        state.editing.value = false;
        validateTime(type);
      },
      
      handleInput: () => {
        if (!state.editing.value) return;
        
        // 如果输入是有效的时间格式，更新时间轴上的位置
        if (TIME_PATTERN.test(state.formatted.value)) {
          state.updatePercentage();
        }
      },
      
      handleClick: (event?: Event) => {
        if (!state.editing.value) {
          state.toggleDropdown(event);
        }
      }
    };
  }
  
  // 创建开始时间和结束时间选择器助手
  const startTimeSelectorHelper = createTimeSelectorHelper('start');
  const endTimeSelectorHelper = createTimeSelectorHelper('end');
  
  // 组件卸载时清理事件监听器
  onUnmounted(() => {
    document.removeEventListener('click', closeStartTimeDropdown);
    document.removeEventListener('click', closeEndTimeDropdown);
  });
  
  // 返回公共API
  return {
    // 状态
    formattedStartTime: timeRangeState.formattedStartTime,
    formattedEndTime: timeRangeState.formattedEndTime,
    startTimePercentage: timeRangeState.startTimePercentage,
    endTimePercentage: timeRangeState.endTimePercentage,
    
    // 下拉选择器状态
    showStartTimeDropdown,
    showEndTimeDropdown,
    
    // 数据
    hours,
    minutes,
    timeRangeState,
    
    // 选择器助手
    startTimeSelectorHelper,
    endTimeSelectorHelper,
    
    // 工具方法
    getHourFromTime,
    getMinuteFromTime,
    timeToPercentage,
    percentageToTime,
    updateStartTimePercentage,
    updateEndTimePercentage,
    
    // 方法 - 下拉框控制
    toggleStartTimeDropdown,
    toggleEndTimeDropdown,
    closeStartTimeDropdown,
    closeEndTimeDropdown,
    closeAllDropdowns,
    
    // 方法 - 时间选择
    selectStartHour,
    selectStartMinute,
    selectEndHour,
    selectEndMinute,
    
    // 方法 - 验证
    validateTime,
    
    // 方法 - 辅助函数
    createTimeSelectorHelper
  };
} 